/**
 * 游戏AI类
 * 负责神经网络的创建、训练和预测
 */
class GameAI {
    /**
     * 初始化AI系统
     * 创建神经网络并设置训练参数
     */
    constructor() {
        // 创建神经网络
        this.network = new brain.NeuralNetwork({
            hiddenLayers: [128, 64],    // 两个隐藏层
            activation: 'relu',          // 使用ReLU激活函数
            inputSize: 42,              // 输入层大小：玩家位置(2) + 球位置(40)
            outputSize: 4               // 输出层大小：4个动作（上下左右）
        });
        
        // 初始化网络
        this.network.train([{
            input: new Array(42).fill(0),
            output: new Array(4).fill(0)
        }], {
            iterations: 1
        });
        
        // 强化学习参数
        this.epsilon = 1.0;              // 探索率（初始值）
        this.minEpsilon = 0.01;          // 最小探索率
        this.epsilonDecay = 0.995;       // 探索率衰减系数
        this.memory = [];                // 经验回放缓冲区
        this.memorySize = 10000;         // 经验回放缓冲区大小
        this.batchSize = 32;             // 批次大小
        this.bestScore = -Infinity;      // 最佳得分记录
        this.trainingCount = 0;          // 训练次数计数器
    }

    /**
     * 预测下一个动作
     * @param {Array} state - 当前游戏状态
     * @returns {number} 预测的动作（0-3）
     */
    predict(state) {
        // Brain.js 直接处理归一化的数据
        const output = this.network.run(state);
        
        // epsilon-greedy策略：随机探索或使用网络预测
        if (Math.random() < this.epsilon) {
            return Math.floor(Math.random() * 4);  // 随机动作
        }
        
        // 使用网络预测最佳动作
        const outputArray = [output[0] || 0, output[1] || 0, output[2] || 0, output[3] || 0];
        return outputArray.indexOf(Math.max(...outputArray));
    }

    /**
     * 存储经验到回放缓冲区
     * @param {Array} state - 当前状态
     * @param {number} action - 执行的动作
     * @param {number} reward - 获得的奖励
     * @param {Array} nextState - 下一个状态
     * @param {boolean} done - 是否结束
     */
    remember(state, action, reward, nextState, done) {
        if (this.memory.length >= this.memorySize) {
            this.memory.shift();  // 如果缓冲区满了，移除最旧的经验
        }
        this.memory.push({state, action, reward, nextState, done});
    }

    /**
     * 训练神经网络
     * @returns {Object|null} 训练结果，包含误差信息
     */
    train() {
        if (this.memory.length < this.batchSize) return null;

        // 获取训练批次
        const batch = this.getBatch();
        
        // 准备训练数据
        const trainingData = batch.map(experience => {
            const targetOutput = new Array(4).fill(0);
            targetOutput[experience.action] = experience.reward;
            
            return {
                input: experience.state,
                output: targetOutput
            };
        });

        // 训练网络
        const result = this.network.train(trainingData, {
            iterations: 1,
            errorThresh: 0.01,
            log: false
        });

        // 更新探索率和计数器
        this.epsilon = Math.max(this.minEpsilon, this.epsilon * this.epsilonDecay);
        this.trainingCount++;

        return result;
    }

    /**
     * 从记忆中随机获取训练批次
     * @returns {Array} 训练数据批次
     */
    getBatch() {
        const indices = new Set();
        while (indices.size < this.batchSize) {
            indices.add(Math.floor(Math.random() * this.memory.length));
        }
        return Array.from(indices).map(index => this.memory[index]);
    }

    /**
     * 将AI状态转换为JSON
     * @returns {Object} AI状态的JSON表示
     */
    toJSON() {
        return {
            network: this.network.toJSON(),
            epsilon: this.epsilon,
            bestScore: this.bestScore,
            trainingCount: this.trainingCount
        };
    }

    /**
     * 从JSON恢复AI状态
     * @param {Object} data - AI状态的JSON数据
     */
    fromJSON(data) {
        try {
            // 加载网络
            if (data.network) {
                this.network.fromJSON(data.network);
            }
            
            // 加载其他状态
            this.epsilon = data.epsilon || this.epsilon;
            this.bestScore = data.bestScore || this.bestScore;
            this.trainingCount = data.trainingCount || this.trainingCount;
            
            console.log('AI 状态已恢复:', {
                epsilon: this.epsilon,
                bestScore: this.bestScore,
                trainingCount: this.trainingCount
            });
        } catch (error) {
            console.error('从 JSON 恢复 AI 失败:', error);
            throw error;
        }
    }

    /**
     * 释放资源（Brain.js不需要手动释放）
     */
    dispose() {
        // Brain.js 不需要手动释放资源
    }
} 